home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / unix / shel301a.1 < prev    next >
Text File  |  1988-12-06  |  59KB  |  2,688 lines

  1. Path: xanth!ames!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i087:  shell - csh-like shell v3.01a, Part01/03
  5. Message-ID: <10488@swan.ulowell.edu>
  6. Date: 5 Dec 88 22:31:49 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2677
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: PERUGIA@ICNUCEVM.BITNET (Cesare Dieni)
  12. Posting-number: Volume 2, Issue 87
  13. Archive-name: unix/shell301a.1
  14.  
  15. [This is a command line interpreter similar to the unix 'csh'.  It is
  16. based on Matt Dillon's shell with Steve Drew's additions.  I do not
  17. have a list of the changes between the original and this version.  See
  18. 'shell.doc' (in part 3) for the full story.  ..Bob]
  19.  
  20. #    This is a shell archive.
  21. #    Remove everything above and including the cut line.
  22. #    Then run the rest of the file through sh.
  23. #----cut here-----cut here-----cut here-----cut here----#
  24. #!/bin/sh
  25. # shar:    Shell Archiver
  26. #    Run the following text with /bin/sh to create:
  27. #    comm1.c
  28. #    comm2.c
  29. #    comm3.c
  30. #    execom.c
  31. # This archive created: Mon Dec  5 17:24:55 1988
  32. cat << \SHAR_EOF > comm1.c
  33. /*
  34.  * COMM1.C
  35.  *
  36.  * Matthew Dillon, August 1986
  37.  *
  38.  * Version 2.07M by Steve Drew 10-Sep-87
  39.  *
  40.  * Version 3.01A by Carlo Borreo & Cesare Dieni 17-Nov-88
  41.  *
  42.  */
  43.  
  44. extern char *v_passed, *v_gotofwd, *v_cwd, *v_lasterr;
  45.  
  46. #define DIR_SHORT 0x01
  47. #define DIR_FILES 0x02
  48. #define DIR_DIRS  0x04
  49.  
  50. extern int has_wild;
  51. char cwd[256];
  52.  
  53. /*
  54.     Parse the options specified in sw[]
  55.     Setting a bit for each one found
  56. */
  57.  
  58. get_opt(sw,count)
  59. char *sw;
  60. int *count;
  61. {
  62. register char *c,*s;
  63. unsigned int l,i = 0;
  64.  
  65. options=0;
  66. while((++i < ac) && (av[i][0] == '-')) {
  67.     for (c = av[i]+1; *c ; c++) {
  68.         for(l = 0,s = sw;*s && *s != *c; ++s) ++l;
  69.         if (*s) options |= (1 << l);
  70.         }
  71.     }
  72. *count = i;
  73. return options;
  74. }
  75.  
  76. do_sleep()
  77. {
  78. int i;
  79.  
  80. if (ac == 2) {
  81.     i = atoi(av[1]);
  82.     while (i > 0) { Delay (100L); i -= 2; if (CHECKBREAK()) break; }
  83.     }
  84. return 0;
  85. }
  86.  
  87. do_protect()
  88. {
  89. register long mask=0xf;
  90. register char *s, *p, *flags="DEWRAPSH";
  91. register unsigned int i;
  92. for (s=av[--ac]; *s; s++)
  93.     if (p=index(flags,Toupper(*s))) mask^=(1 << (p-flags));
  94.     else ierror(av[ac],500);
  95. for (i=1; i<ac; i++) if (!SetProtection(av[i],mask)) pError(av[i]);
  96. return 0;
  97. }
  98.  
  99. do_filenote()
  100. {
  101. char *note=av[--ac];
  102. register unsigned int i;
  103.  
  104. for (i=1; i<ac; i++) if (!SetComment(av[i], note)) pError(av[i]);
  105. return 0;
  106. }
  107.  
  108. do_cat()
  109. {
  110. FILE *fopen(), *fi;
  111. register unsigned int lctr;
  112. unsigned int i;
  113. char buf[256];
  114.  
  115. get_opt("n",&i);
  116. if (i>=ac) {
  117.     while (gets(buf) && !dobreak()) {
  118.         if (options) printf("%4d ",++lctr);
  119.         puts(buf);
  120.         }
  121.     }
  122. for (; i<ac; i++)
  123.     if (fi = fopen (av[i], "r")) {
  124.         lctr=0;
  125.         while (fgets(buf,256,fi) && !dobreak()) {
  126.             if (options) printf("%4d ",++lctr);
  127.             printf("%s",buf);
  128.             }
  129.         fclose (fi);
  130.         }
  131.     else pError(av[i]);
  132. }
  133.  
  134. do_info()
  135. {
  136. BPTR lock;
  137. struct InfoData *info;
  138. unsigned int size, free;
  139. char *p,*s,*state;
  140. struct DirectoryEntry *de_head=NULL, *de;
  141.  
  142. info=(struct InfoData *)AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC);
  143. AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  144. Myprocess->pr_WindowPtr = (APTR)(-1);
  145. printf ("Unit  Size  Bytes  Used Blk/By-Free Full Errs  Status    Name\n");
  146. for (de=de_head; de; de=de->de_Next) {
  147.     printf("%-5s",de->de_Name);
  148.     if (lock=Lock(de->de_Name,ACCESS_READ)) {
  149.         if (Info(lock, info)) {
  150.         s = get_pwd(lock);
  151.         if (p=index(s,':')) *p = '\0';
  152.         size = ((info->id_NumBlocks + 2)* info->id_BytesPerBlock)/ 1024;
  153.         free = (((info->id_NumBlocks-info->id_NumBlocksUsed))*
  154.                info->id_BytesPerBlock)/ 1024;
  155.         switch(info->id_DiskState) {
  156.             case ID_WRITE_PROTECTED: state="Read Only "; break;
  157.             case ID_VALIDATED:     state="Read/Write"; break;
  158.             case ID_VALIDATING:     state="Validating"; break;
  159.             }
  160.         printf("%4d%c%6ld%7ld%7ld%4d%c%4ld%%%4ld  %s %s\n",
  161.             (size>1024) ? ((size+512) >> 10) : size,
  162.             (size>1024) ? 'M' : 'K',
  163.             info->id_BytesPerBlock,
  164.             info->id_NumBlocksUsed,
  165.             info->id_NumBlocks-info->id_NumBlocksUsed,
  166.             (free>1024) ? ((free+512) >> 10) : free,
  167.             (free>1024) ? 'M' : 'K',
  168.             (info->id_NumBlocksUsed * 100)/info->id_NumBlocks,
  169.             info->id_NumSoftErrors,
  170.             state,
  171.             s);
  172.         }
  173.         else pError (de->de_Name);
  174.         UnLock(lock);
  175.         }
  176.     else puts("  No disk present");
  177.     }
  178. FreeDAList(&de_head);
  179. Myprocess->pr_WindowPtr = NULL;
  180. FreeMem(info,(long)sizeof(struct InfoData));
  181. return 0;
  182. }
  183.  
  184. /* things shared with display_file */
  185.  
  186. char lspec[128];
  187. int filecount, col;
  188. long bytes, blocks;
  189.  
  190. /*
  191.  * the args passed to do_dir will never be expanded
  192.  */
  193. do_dir()
  194. {
  195.    void display_file();
  196.    int i;
  197.  
  198.    col = filecount = 0;
  199.    bytes = blocks = 0L;
  200.    *lspec = '\0';
  201.  
  202.    get_opt("sfd",&i);
  203.  
  204.    if (ac == i) {
  205.       ++ac;
  206.       av[i] = "";
  207.    }
  208.    if (!(options & (DIR_FILES | DIR_DIRS)))  options|=(DIR_FILES | DIR_DIRS);
  209.  
  210.    for (; i < ac; ++i) {
  211.       char **eav;
  212.       int c,eac;
  213.       if (!(eav = expand(av[i], &eac)))
  214.       continue;
  215.       QuickSort(eav, eac);
  216.       for(c=0;c < eac && !breakcheck();++c) display_file(options,eav[c]);
  217.       free_expand (eav);
  218.       if (CHECKBREAK()) break;
  219.    }
  220.    if (col)  printf("\n");
  221.    if (filecount > 1) {
  222.       blocks += filecount; /* account for dir blocks */
  223.       printf (" %ld Blocks, %ld Bytes used in %d files\n", blocks, bytes, filecount);
  224.    }
  225.    return (0);
  226. }
  227.  
  228. void
  229. display_file(options,filestr)
  230. int options;
  231. char *filestr;
  232. {
  233.    long atol();
  234.    int isadir,slen;
  235.    char sc;
  236.    char *c,*s,*fi;
  237.    BPTR lock;
  238.  
  239. /*    if current dir different from lspec then
  240.     look for ':' or '/' if found lock it and get_pwd.
  241.     else then use cwd.
  242. */
  243.    for(s = c = filestr; *c; ++c) if (*c == ':' || *c == '/') s = c;
  244.    if (*s == ':') ++s;
  245.    sc = *s;
  246.    *s = '\0';
  247.    c = filestr;
  248.    if (!*c) c = cwd;
  249.    if (strcmp (c, &lspec))  {
  250.     strcpy(lspec, c);
  251.     if (col) printf("\n");
  252.     if (lock=Lock(c,SHARED_LOCK)) {
  253.         printf("Directory of %s\n", get_pwd(lock));
  254.         UnLock(lock);
  255.         }
  256.     col = 0;
  257.     }
  258.    *s = sc;
  259.    if (sc == '/') s++;
  260.    slen = strlen(s);
  261.    fi = s + slen + 1;
  262.    isadir = (fi[12] =='D');
  263.  
  264.    if (!(((options & DIR_FILES) && !isadir) ||
  265.       ((options & DIR_DIRS) &&  isadir)))
  266.       return;
  267.    if (isadir) printf ("\23333m");
  268.    if (options & DIR_SHORT) {
  269.     if (col==3 && slen>18) { printf("\n"); col = 0; }
  270.     if (slen>18) { printf(" %-37s",s); col+= 2; }
  271.         else { printf(" %-18s",s); col++; }
  272.     if (col > 3) { printf("\n"); col=0; }
  273.     }
  274.    else printf("   %-24s %s",s ,fi);
  275.    if (isadir) printf("\2330m");
  276.    fflush(stdout);
  277.    fi[16] = fi[21] = '\0';
  278.    bytes  += atol(fi+10);
  279.    blocks += atol(fi+17);
  280.    filecount++;
  281.    return;
  282. }
  283.  
  284. do_quit()
  285. {
  286. if (Src_stack) {
  287.     Quit = 1;
  288.     return(do_return());
  289.     }
  290. main_exit(0);
  291. }
  292.  
  293. do_echo(str)
  294. register char *str;
  295. {
  296. char nl=1;
  297.  
  298. for (; *str && *str != ' '; ++str);
  299. if (*str==' ') ++str;
  300. if (av[1] && !strcmp(av[1],"-n")) {
  301.     nl = 0;
  302.     str += 2;
  303.     if (*str==' ') ++str;
  304.     }
  305. printf("%s",str);
  306. if (nl) printf("\n");
  307. fflush(stdout);
  308. return 0;
  309. }
  310.  
  311. do_source(str)
  312. char *str;
  313. {
  314.    register FILE *fi;
  315.    char buf[256];
  316.  
  317.    if (Src_stack == MAXSRC) {
  318.       ierror(NULL,217);
  319.       return(-1);
  320.    }
  321.    if ((fi = fopen (av[1], "r")) == 0) {
  322.       ierror(av[1], 205);
  323.       return(-1);
  324.    }
  325.    set_var(LEVEL_SET, v_passed, next_word(next_word(str)));
  326.    ++H_stack;
  327.    Src_pos[Src_stack] = 0;
  328.    Src_base[Src_stack] = (long)fi;
  329.    ++Src_stack;
  330.    while (fgets (buf, 256, fi)) {
  331.       int len = strlen(buf);
  332.       buf[len-1] = '\0';
  333.       Src_pos[Src_stack - 1] += len;
  334.       if (Verbose && !forward_goto)
  335.       fprintf(stderr,"%s\n",buf);
  336.       exec_command (buf);
  337.       if (CHECKBREAK())
  338.       break;
  339.    }
  340.    --H_stack;
  341.    --Src_stack;
  342.    if (forward_goto)
  343.       ierror(NULL,501);
  344.    forward_goto = 0;
  345.    unset_level(LEVEL_LABEL + Src_stack);
  346.    unset_var(LEVEL_SET, v_gotofwd);
  347.    unset_var(LEVEL_SET, v_passed);
  348.    fclose (fi);
  349.    return (0);
  350. }
  351.  
  352. /*
  353.  * return ptr to string that contains full cwd spec.
  354.  */
  355. char *get_pwd(flock)
  356. BPTR flock;
  357. {
  358. static char pwdstr[130];
  359. PathName(flock, pwdstr, 128L);
  360. return pwdstr;
  361. }
  362.  
  363. /*
  364.  * set process cwd name and $_cwd, if str != NULL also print it.
  365.  */
  366. do_pwd(str)
  367. char *str;
  368. {
  369. char *ptr;
  370.  
  371. if (Myprocess->pr_CurrentDir == 0)
  372.     attempt_cd(":"); /* if we just booted 0 = root lock */
  373. strcpy(cwd,get_pwd(Myprocess->pr_CurrentDir,1));
  374. if (str) puts(cwd);
  375. set_var(LEVEL_SET, v_cwd, cwd);
  376. /* put the current dir name in our CLI task structure */
  377. CtoBStr(cwd, Mycli->cli_SetName, 128L);
  378.  
  379. /*
  380. ptr=(char *)((ULONG)Mycli->cli_SetName << 2);
  381. ptr[0] = strlen(cwd);
  382. movmem(cwd,ptr+1,(int)ptr[0]);
  383. return 0;
  384. */
  385. }
  386.  
  387. /*
  388.  * CD
  389.  *
  390.  * CD(str, 0)      -do CD operation.
  391.  *
  392.  *    standard operation: breakup path by '/'s and process independantly
  393.  *    x:    -reset cwd base
  394.  *    ..    -remove last cwd element
  395.  *    N     -add N or /N to cwd
  396.  */
  397.  
  398. do_cd(str)
  399. char *str;
  400. {
  401.    char sc, *ptr;
  402.    int err=0;
  403.  
  404.    str = next_word(str);
  405.    if (*str == '\0') {
  406.       puts(cwd);
  407.       return(0);
  408.    }
  409.    str[strlen(str)+1] = '\0';        /* add second \0 on end */
  410.    while (*str) {
  411.       for (ptr = str; *ptr && *ptr != '/' && *ptr != ':'; ++ptr);
  412.       switch (*ptr) {
  413.       case ':':
  414.       sc = ptr[1];
  415.       ptr[1] = '\0';
  416.       err = attempt_cd(str);
  417.       ptr[1] = sc;
  418.       break;
  419.       case '\0':
  420.       case '/':
  421.       *ptr = '\0';
  422.       if (strcmp(str, "..") == 0 || str == ptr)
  423.          str = "/";
  424.       if (*str) err = attempt_cd(str);
  425.       break;
  426.       }
  427.       if (err) break;
  428.       str = ptr + 1;
  429.    }
  430.    do_pwd(NULL);      /* set $_cwd */
  431.    return(err);
  432. }
  433.  
  434. attempt_cd(str)
  435. char *str;
  436. {
  437. BPTR oldlock, filelock;
  438.  
  439. if (filelock=Lock(str, ACCESS_READ)) {
  440.     if (isdir(str)) {
  441.         if (oldlock=CurrentDir(filelock)) UnLock(oldlock);
  442.         return (0);
  443.         }
  444.     UnLock(filelock);
  445.     ierror(str, 212);
  446.     }
  447. else ierror(str, 205);
  448. return -1;
  449. }
  450.  
  451. do_mkdir()
  452. {
  453. register unsigned int i;
  454. BPTR lock;
  455.  
  456. for (i=1; i<ac; ++i) {
  457.     if (exists(av[i])) ierror(av[i],203);
  458.     else if (lock=CreateDir(av[i])) UnLock (lock);
  459.     else pError(av[i]);
  460.     }
  461. return 0;
  462. }
  463.  
  464. do_mv()
  465. {
  466. char *dest, buf[256];
  467. int dirflag;
  468. register unsigned int i;
  469.  
  470. dirflag=isdir(dest=av[--ac]);
  471. if (ac>3 && !dirflag) { ierror(dest, 507); return (-1); }
  472. for (i=1; i<ac; ++i) {
  473.     strcpy(buf, dest);
  474.     if (dirflag) TackOn(buf, BaseName(av[i]));
  475.     if (Rename(av[i],buf)==0)
  476.         { pError(av[i]); return -1; }
  477.     }
  478. return 0;
  479. }
  480.  
  481. int dirstoo;
  482.  
  483. all_args(args, action, dirsflag)
  484. char *args;
  485. int (*action)();
  486. {
  487. unsigned int i;
  488.  
  489. get_opt(args, &i);
  490. dirstoo=dirsflag;
  491. for (; i<ac && !dobreak(); ++i)
  492.     if (isdir(av[i])) {
  493.         if (options & 1) recurse(av[i], action);
  494.             else if (dirstoo) (*action)(av[i]);
  495.         }
  496.     else (*action)(av[i]);
  497. return 0;
  498. }
  499.  
  500. char *searchstring;
  501.  
  502. search_file(s)
  503. char *s;
  504. {
  505. FILE *fopen(), *fi;
  506. unsigned int lctr, len=strlen(searchstring);
  507. int yesno;
  508. char buf[256], lowbuf[256], first;
  509. register char *p, *l, *t;
  510.  
  511. if (!(options & 2)) for (t=searchstring; *t=Toupper(*t); t++);
  512. first=*searchstring;
  513. if ((fi=fopen(s, "r"))==NULL) { pError(s); return; }
  514. lctr=0;
  515. if (!(options & 32)) printf("Examining %s...\n",s);
  516. while (fgets(buf,256,fi) && !dobreak()) {
  517.     lctr++;
  518.     if (options & 4) yesno=compare_ok(searchstring,buf);
  519.     else {
  520.         yesno=0;
  521.         p=buf;
  522.         if (!(options & 2)) {
  523.             l=lowbuf;            /* p is already =buf */
  524.             while (*l++=Toupper(*p++));    /* lowbuf=upper(buf) */
  525.             p=lowbuf;
  526.             }
  527.         while (p=index(p,first))
  528.             if (!strncmp(p++,searchstring,len)) { yesno=1; break; }
  529.         }
  530.     if (yesno ^ ((options & 16)!=0) ) {
  531.             /* default: print line numbers */
  532.         if (!(options & 8)) printf("%4d ",lctr);
  533.         printf("%s",buf);
  534.         }
  535.     }
  536. fclose (fi);
  537. }
  538.  
  539. do_search()
  540. {
  541. searchstring=av[--ac];
  542. all_args("rcwneq", search_file, 0);
  543. return 0;
  544. }
  545.  
  546. rm_file(file)
  547. char *file;
  548. {
  549. if (has_wild) printf(" %s...",file);
  550. if (options & 2) SetProtection(file,0L);
  551. if (!DeleteFile(file)) pError (file); else if (has_wild) printf("Deleted\n");
  552. }
  553.  
  554. do_rm()
  555. {
  556. all_args("rp", rm_file, 1);
  557. return 0;
  558. }
  559.  
  560. recurse(name, action)
  561. char *name;
  562. int (*action)();
  563. {
  564. register BPTR lock, cwd;
  565. register FIB *fib=(FIB *)AllocMem((long)sizeof(FIB),MEMF_PUBLIC);
  566. char *namecopy=malloc(256);
  567.  
  568. if (name[0] =='\0') return;
  569. namecopy[0]=0;
  570. if (lock=Lock(name,ACCESS_READ)) {
  571.     cwd =CurrentDir(lock);
  572.     if (Examine(lock, fib))
  573.     while (ExNext(lock, fib) && !CHECKBREAK()) {
  574.         if (*namecopy) { (*action)(namecopy); namecopy[0]=0; }
  575.         if (fib->fib_DirEntryType>=0) recurse(fib->fib_FileName,action);
  576.         else strcpy(namecopy,fib->fib_FileName);
  577.         }
  578.     if (*namecopy) (*action)(namecopy);
  579.     UnLock(CurrentDir(cwd));
  580.     if (dirstoo) (*action)(name);
  581.     }
  582. else pError(name);
  583. free(namecopy);
  584. FreeMem(fib, (long)sizeof(FIB));
  585. }
  586.  
  587. do_history()
  588. {
  589. register struct HIST *hist;
  590. int i = H_tail_base;
  591. int len = (av[1]) ? strlen(av[1]) : 0;
  592.  
  593. for (hist = H_tail; hist && !dobreak(); hist = hist->prev)
  594.     if (len == 0 || !strncmp(av[1], hist->line, len))
  595.         printf("%3d %s", i++, hist->line);
  596. return 0;
  597. }
  598.  
  599. do_mem()
  600. {
  601. long cfree, ffree;
  602. extern long AvailMem();
  603.  
  604. Forbid();
  605. cfree = AvailMem (MEMF_CHIP);
  606. ffree = AvailMem (MEMF_FAST);
  607. Permit();
  608. if (ffree) printf ("FAST memory: %ld\nCHIP memory: %ld\n", ffree, cfree);
  609. printf("Total  Free: %ld\n", cfree+ffree);
  610. return 0;
  611. }
  612.  
  613. /*
  614.  * foreach var_name  ( str str str str... str ) commands
  615.  * spacing is important (unfortunately)
  616.  *
  617.  * ac=0    1 2 3 4 5 6 7
  618.  * foreach i ( a b c ) echo $i
  619.  * foreach i ( *.c ) "echo -n "file ->";echo $i"
  620.  */
  621.  
  622. do_foreach()
  623. {
  624.    register int i, cstart, cend;
  625.    register char *cstr, *vname;
  626.    char **fav;
  627.  
  628.    cstart = i = (*av[2] == '(') ? 3 : 2;
  629.    while (i < ac) {
  630.       if (*av[i] == ')')
  631.       break;
  632.       ++i;
  633.    }
  634.    if (i == ac) {
  635.       fprintf (stderr,"')' expected\n");
  636.       return (-1);
  637.    }
  638.    ++H_stack;
  639.    cend = i;
  640.  
  641.    vname = strcpy(malloc(strlen(av[1])+1), av[1]);
  642.    fav = (char **)malloc(sizeof(char *) * (ac));
  643.    cstr = compile_av (av, cend + 1, ac, ' ');
  644.  
  645.    for (i = cstart; i < cend; ++i) {
  646.      fav[i] = av[i];
  647.    }
  648.  
  649.    for (i = cstart; i < cend; ++i) {
  650.       set_var (LEVEL_SET, vname, fav[i]);
  651.       if (CHECKBREAK())
  652.       break;
  653.       exec_command (cstr);
  654.    }
  655.    --H_stack;
  656.    free (fav);
  657.    free (cstr);
  658.    unset_var (LEVEL_SET, vname);
  659.    free (vname);
  660.    return (0);
  661. }
  662.  
  663. do_forever(str)
  664. char *str;
  665. {
  666.    int rcode = 0;
  667.    char *ptr = next_word(str);
  668.  
  669.    ++H_stack;
  670.    for (;;) {
  671.       if (CHECKBREAK()) {
  672.       rcode = 20;
  673.       break;
  674.       }
  675.       if (exec_command (ptr) < 0) {
  676.       str = get_var(LEVEL_SET, v_lasterr);
  677.       rcode = (str) ? atoi(str) : 20;
  678.       break;
  679.       }
  680.    }
  681.    --H_stack;
  682.    return (rcode);
  683. }
  684.  
  685. extern struct Window *w;
  686. extern struct IntuitionBase *IntuitionBase;
  687.  
  688. do_window()
  689. {
  690. long x, y, maxwidth, maxheight, arg[5];
  691. unsigned int i;
  692. struct Screen *screen;
  693. struct Window *window;
  694.  
  695. get_opt("slfbaq", &i);
  696. if (options & 1)
  697.     SizeWindow(w, (long)(w->MinWidth-w->Width), (long)(w->MinHeight-w->Height));
  698. if (options & 2) {
  699.     x=-w->LeftEdge;
  700.     y=-w->TopEdge;
  701.     MoveWindow(w,x,y);
  702.     x=IntuitionBase->ActiveScreen->Width -w->Width;
  703.     y=IntuitionBase->ActiveScreen->Height-w->Height;
  704.     SizeWindow(w,x,y);
  705.     }
  706. if (options & 4) WindowToFront(w);
  707. if (options & 8) WindowToBack(w);
  708. if (options & 16) ActivateWindow(w);
  709. if(ac >= 5) {
  710.     Errno = 0;
  711.     for(i=1; i<5; i++) {
  712.         arg[i] = myatol(av[i]);
  713.         if (Errno || arg[i] < 0) {
  714.             ierror(av[i], 500);
  715.             return 20;
  716.             }
  717.         }
  718.     maxwidth = w->WScreen->Width;
  719.     maxheight= w->WScreen->Height;
  720.     if (arg[3] > maxwidth - arg[1] || arg[4] > maxheight- arg[2]) {
  721.         ierror(NULL, 500);
  722.         return 20;
  723.         }
  724.     x = -w->LeftEdge;
  725.     y = -w->TopEdge;
  726.     MoveWindow(w, x, y);
  727.     x = arg[3] - w->Width;
  728.     y = arg[4] - w->Height;
  729.     SizeWindow(w, x, y);
  730.     x = arg[1];
  731.     y = arg[2];
  732.     MoveWindow(w, x, y);
  733.     }
  734. if(options & 32) {
  735.     for (screen=IntuitionBase->FirstScreen; screen; screen=screen->NextScreen) {
  736.         printf("\nScreen \"%s\" (%dx%d):\n",
  737.             screen->Title,
  738.             screen->Width,
  739.             screen->Height
  740.             );
  741.         for (window=screen->FirstWindow; window; window=window->NextWindow) {
  742.         printf("\tWindow\t\"%s\" (%dx%d)\n",
  743.             window->Title,
  744.             window->Width,
  745.             window->Height
  746.             );
  747.         }
  748.         }
  749.     return 0;
  750.     }
  751. printf("\014");
  752. return 0;
  753. }
  754.  
  755. setsystemtime(ds)
  756. struct DateStamp *ds;
  757. {
  758. struct timerequest tr;
  759. long secs= ds->ds_Days*86400 + ds->ds_Minute*60 + ds->ds_Tick/TICKS_PER_SECOND;
  760.  
  761. if (OpenDevice(TIMERNAME, UNIT_VBLANK, &tr, 0L)) {
  762.     fprintf(stderr,"Clock error: can't open timer device\n");
  763.     return;
  764.     }
  765. tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  766. tr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
  767. tr.tr_node.io_Message.mn_Node.ln_Name = NULL;
  768. tr.tr_node.io_Message.mn_ReplyPort = NULL;
  769. tr.tr_node.io_Command = TR_SETSYSTIME;
  770. tr.tr_time.tv_secs = secs;
  771. tr.tr_time.tv_micro = 0L;
  772. if (DoIO (&tr)) fprintf(stderr,"Clock error: can't talk to timer device\n");
  773. CloseDevice (&tr);
  774. }
  775.  
  776. char tday[10];
  777.  
  778. char *dates(dss)
  779. struct DateStamp *dss;
  780. {
  781. static char timestr[40];
  782. char tdate[10], ttime[10];
  783. struct DateTime dt;
  784. struct DateStamp *myds=&(dt.dat_Stamp);
  785.  
  786. dt.dat_Format=FORMAT_DOS;
  787. dt.dat_StrDay=tday;
  788. dt.dat_StrDate=tdate;
  789. dt.dat_StrTime=ttime;
  790. dt.dat_Flags=NULL;
  791. myds->ds_Days=dss->ds_Days;
  792. myds->ds_Minute=dss->ds_Minute;
  793. myds->ds_Tick=dss->ds_Tick;
  794. StamptoStr(&dt);
  795. sprintf(timestr,"%s %s\n",tdate,ttime);
  796. timestr[18]='\n';
  797. timestr[19]='\0';    /* protection against bad timestamped files */
  798. return timestr;
  799. }
  800.  
  801. date()
  802. {
  803. struct DateStamp dss;
  804. register unsigned short i;
  805. struct DateTime dt;
  806.  
  807. dt.dat_Format=FORMAT_DOS;
  808. if (ac==1) {
  809.     DateStamp(&dss);
  810.     printf("%s %s",tday,dates(&dss));
  811.     }
  812. else {
  813.     DateStamp(& (dt.dat_Stamp));
  814.     for (i=1; i<ac; i++) {
  815.         dt.dat_StrDate=NULL;
  816.         dt.dat_StrTime=NULL;
  817.         dt.dat_Flags=DTF_FUTURE;
  818.         if (index(av[i],':')) dt.dat_StrTime=av[i];
  819.             else dt.dat_StrDate=av[i];
  820.         if (StrtoStamp(&dt)) ierror(av[i],500);
  821.         }
  822.     setsystemtime( & (dt.dat_Stamp) );
  823.     }
  824. return 0;
  825. }
  826. SHAR_EOF
  827. cat << \SHAR_EOF > comm2.c
  828. /*
  829.  * COMM2.C
  830.  *
  831.  * (c)1986 Matthew Dillon     9 October 1986
  832.  *
  833.  * Version 2.07M by Steve Drew 10-Sep-87
  834.  *
  835.  * Version 3.01A by Carlo Borreo & Cesare Dieni 17-Nov-88
  836.  *
  837.  */
  838.  
  839. extern char *v_gotofwd;
  840.  
  841. /* Casting conveniences */
  842. #define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
  843. #define PROC(task)              ((struct Process *)task)
  844. #define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))
  845.  
  846. /* Externs */
  847. extern int has_wild;                    /* flag set if any arg has a ? or * */
  848.  
  849. /* globals */
  850. int cp_update;
  851. int cp_date;
  852.  
  853. do_abortline()
  854. {
  855. Exec_abortline = 1;
  856. return 0;
  857. }
  858.  
  859. do_return()
  860. {
  861. register int retcode=(ac<2 ? 0 : atoi(av[1]));
  862.    Exec_abortline = 1;
  863.    if (Src_stack) {
  864.        FILE *ptr = (FILE *)Src_base[Src_stack - 1];
  865.        ptr->_bp = ptr->_bend;
  866.        ptr->_flags |= _EOF;
  867. /*     fseek (Src_base[Src_stack - 1], 0L, 2); */
  868.       return retcode;
  869.    } else main_exit(retcode);
  870. }
  871.  
  872. /*
  873.  * STRHEAD
  874.  *
  875.  * place a string into a variable removing everything after and including
  876.  * the 'break' character
  877.  *
  878.  * strhead varname breakchar string
  879.  *
  880.  */
  881.  
  882. do_strhead()
  883. {
  884. char *s;
  885. if (s=index(av[3],*av[2])) *s='\0';
  886. set_var (LEVEL_SET, av[1], av[3]);
  887. }
  888.  
  889. do_strtail()
  890. {
  891. char *s;
  892. if (s=index(av[3],*av[2])) s++; else s=av[3];
  893. set_var (LEVEL_SET, av[1], s);
  894. }
  895.  
  896. long dptrtosecs(d)
  897. struct DPTR *d;
  898. {
  899. register struct DateStamp *ds=(&d->fib->fib_Date);
  900. return ds->ds_Days*86400 + ds->ds_Minute*60 + ds->ds_Tick/TICKS_PER_SECOND;
  901. }
  902.  
  903. long timeof(s)
  904. char *s;
  905. {
  906. struct DPTR *d;
  907. int dummy;
  908. long n;
  909.  
  910. if ( (d=dopen(s,&dummy))==NULL ) return 0L;
  911. n=dptrtosecs(d);
  912. dclose(d);
  913. return n;
  914. }
  915.  
  916. /*
  917.  * if -f file (exists) or:
  918.  *
  919.  * if A < B   <, >, =, <=, >=, <>, where A and B are either:
  920.  * nothing
  921.  * a string
  922.  * a value (begins w/ number)
  923.  */
  924.  
  925. do_if(garbage, com)
  926. char *garbage;
  927. {
  928. int result;
  929. int i;
  930.  
  931. switch (com) {
  932.     case 0:
  933.     if (If_stack && If_base[If_stack - 1]) If_base[If_stack++] = 1;
  934.     else {
  935.         get_opt("rftmdn",&i);
  936.         result=evalif(i);
  937.         If_base[If_stack++]=(options & 32 ? result : !result);
  938.         }
  939.     break;
  940.     case 1:
  941.     if (If_stack > 1 && If_base[If_stack - 2]) break;
  942.     if (If_stack) If_base[If_stack - 1] ^= 1;
  943.     break;
  944.     case 2:
  945.     if (If_stack) --If_stack;
  946.     break;
  947.      }
  948. disable = (If_stack) ? If_base[If_stack - 1] : 0;
  949. if (If_stack >= MAXIF) {
  950.     fprintf(stderr,"If's too deep\n");
  951.     disable = If_stack = 0;
  952.     return -1;
  953.     }
  954. if (forward_goto) disable = If_base[If_stack - 1] = 0;
  955. return 0;
  956. }
  957.  
  958. evalif(i)
  959. register unsigned int i;
  960. {
  961. char c;
  962. long num, t0;
  963. long AvailMem();
  964.  
  965. switch(options & ~32) {
  966.     case 0:
  967.     if (ac-i != 3) return (ac>i && *av[i]);
  968.     Errno=0;
  969.     num=Atol(av[i])-Atol(av[i+2]);
  970.     if (Errno) num=strcmp(av[i],av[i+2]);
  971.     if (num < 0)      c='<';
  972.     else if (num > 0) c='>';
  973.     else if (num ==0) c='=';
  974.     return index(av[i+1], c) != NULL;
  975.     case 1:
  976.     return do_rpn(NULL,i);
  977.     case 2:
  978.     return exists(av[i]);
  979.     case 4:
  980.     t0=timeof(av[i++]);
  981.     for ( ; i<ac ; i++)
  982.         if (t0<=timeof(av[i])) return 1;
  983.     return 0;
  984.     case 8:
  985.     return (AvailMem( (long)MEMF_FAST )!=0);
  986.     case 16:
  987.     return (isdir(av[i])!=0);
  988.     default:
  989.     ierror(NULL,500);
  990.     return 0;
  991.     }
  992. }
  993.  
  994. do_label()
  995. {
  996.    char aseek[32];
  997.  
  998.    if (Src_stack == 0) {
  999.       ierror (NULL, 502);
  1000.       return (-1);
  1001.    }
  1002.  
  1003.    sprintf (aseek, "%ld %d", Src_pos[Src_stack-1], If_stack);
  1004.    set_var (LEVEL_LABEL + Src_stack - 1, av[1], aseek);
  1005.    if (!strcmp(av[1],get_var(LEVEL_SET,v_gotofwd)))
  1006.       forward_goto = 0;
  1007.    return (0);
  1008. }
  1009.  
  1010. do_goto()
  1011. {
  1012.    int new;
  1013.    long pos;
  1014.    char *lab;
  1015.  
  1016.    if (Src_stack == 0) {
  1017.       ierror (NULL, 502);
  1018.    } else {
  1019.       lab = get_var (LEVEL_LABEL + Src_stack - 1, av[1]);
  1020.       if (lab == NULL) {
  1021.          forward_goto = 1;
  1022.          set_var (LEVEL_SET, v_gotofwd, av[1]);
  1023.          return(0);
  1024.       } else {
  1025.          pos = atoi(lab);
  1026.          fseek (Src_base[Src_stack - 1], pos, 0);
  1027.          Src_pos[Src_stack - 1] = pos;
  1028.          new = atoi(next_word(lab));
  1029.          for (; If_stack < new; ++If_stack)
  1030.             If_base[If_stack] = 0;
  1031.          If_stack = new;
  1032.       }
  1033.    }
  1034.    Exec_abortline = 1;
  1035.    return (0);      /* Don't execute rest of this line */
  1036. }
  1037.  
  1038.  
  1039. do_inc(garbage, com)
  1040. char *garbage;
  1041. {
  1042. char *var, num[32];
  1043.  
  1044. if (ac>2) com *= atoi(av[2]);
  1045. if (var = get_var (LEVEL_SET, av[1])) {
  1046.     sprintf (num, "%d", atoi(var)+com);
  1047.     set_var (LEVEL_SET, av[1], num);
  1048.     }
  1049. }
  1050.  
  1051. do_input()
  1052. {
  1053. char in[256], *p,*s;
  1054. unsigned int i;
  1055.  
  1056. for (i=1; i < ac; ++i)
  1057.     if (gets(in)) {
  1058.     for(p = in; *p; p = s) {
  1059.         s = next_word(p);
  1060.         if (*s) *(s-1) = 0xA0;
  1061.         }
  1062.     set_var (LEVEL_SET, av[i], in);
  1063.     }
  1064. return 0;
  1065. }
  1066.  
  1067. do_ver()
  1068. {
  1069. puts("Shell V3.01A\n\
  1070. (c)1986 Matthew Dillon\n\
  1071. Manx (M) versions by Steve Drew\n\
  1072. ARP (A) versions by Carlo Borreo & Cesare Dieni\n");
  1073. return 0;
  1074. }
  1075.  
  1076. do_ps()
  1077. {
  1078. /* this code fragment based on ps.c command by Dewi Williams */
  1079.  
  1080. register int    count;        /* loop variable        */
  1081. struct Task    *task;        /* EXEC descriptor        */
  1082. char        strbuf[64+1];    /* scratch for btocstr()    */
  1083. char        cmd[40+1];    /* holds cmd name        */
  1084. long ncli;
  1085.  
  1086. printf("Proc Command Name         CLI Type    Pri.  Address  Directory\n");
  1087. Forbid();
  1088.  
  1089. ncli=(long)FindCLI(0L);
  1090. for (count = 1; count <= ncli ; count++)
  1091.         /* or just assume 20?*/
  1092.     if (task = (struct Task *)FindCLI((long)count)) {
  1093.     if (task==NULL) continue;
  1094.     /* Sanity check just in case */
  1095.     if (PROC(task)->pr_TaskNum == 0 || PROC(task)->pr_CLI == 0) continue;
  1096.                             /* or complain? */
  1097.     BtoCStr(cmd,   CLI(PROC(task))->cli_CommandName, 40L);
  1098.     BtoCStr(strbuf,CLI(PROC(task))->cli_SetName    , 64L);
  1099.     printf("%2d   %-20.20s %-11.11s %3d  %8lx  %s\n",
  1100.         count,
  1101.         cmd,
  1102.         task->tc_Node.ln_Name,
  1103.         task->tc_Node.ln_Pri,
  1104.         task,
  1105.         strbuf);
  1106.     }
  1107. Permit();
  1108. return 0;
  1109. }
  1110.  
  1111. /*
  1112.  * CP [-d] [-u] file file
  1113.  * CP [-d] [-u] file file file... destdir
  1114.  * CP [-r][-u][-d] dir dir dir... destdir
  1115.  */
  1116.  
  1117. char *errstr;          /* let's be alittle more informative */
  1118.  
  1119. do_copy()
  1120. {
  1121. register int recur, ierr;
  1122. register char *destname;
  1123. register char destisdir;
  1124. register FIB *fib;
  1125. int i;
  1126.  
  1127. errstr = "";
  1128. ierr = 0;
  1129.  
  1130. fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  1131.  
  1132. get_opt("rud",&i);
  1133. recur     = (options & 0x01);
  1134. cp_update = (options & 0x02);
  1135. cp_date   = (!(options & 0x04)); /* the default is keep orignal file date */
  1136.  
  1137. destname = av[ac - 1];
  1138.  
  1139. if (ac < i + 2) {
  1140.     ierr = 500;
  1141.     goto done;
  1142.     }
  1143. destisdir = isdir(destname);
  1144. if (ac > i + 2 && !destisdir) {
  1145.     ierr = 507;
  1146.     goto done;
  1147.     }
  1148.  
  1149. /*
  1150.  * copy set:                        reduce to:
  1151.  *    file to file                     file to file
  1152.  *    dir  to file (NOT ALLOWED)
  1153.  *    file to dir                      dir to dir
  1154.  *    dir  to dir                      dir to dir
  1155.  *
  1156.  */
  1157.  
  1158. for (; i<ac-1 && !dobreak(); ++i) {
  1159.     short srcisdir = isdir(av[i]);
  1160.     if (srcisdir && has_wild && (ac >2)) /* hack to stop dir's from */
  1161.         continue;             /* getting copied if specified */
  1162.                          /* from wild expansion */
  1163.     if (srcisdir) {
  1164.         BPTR srcdir, destdir;
  1165.         if (!destisdir) {
  1166.             if (exists(destname)) {
  1167.                 ierr = 507;    /* disallow dir to file */
  1168.                 goto done;
  1169.                 }
  1170.             if (destdir = CreateDir(destname)) UnLock(destdir);
  1171.             destisdir = 1;
  1172.             }
  1173.         if (!(destdir = Lock(destname, ACCESS_READ))) {
  1174.             ierr = 205;
  1175.             errstr = destname;
  1176.             goto done;
  1177.             }
  1178.         if (!(srcdir = Lock(av[i], ACCESS_READ))) {
  1179.             ierr = 205;
  1180.             errstr = av[i];
  1181.             UnLock(destdir);
  1182.             goto done;
  1183.             }
  1184.         ierr = copydir(srcdir, destdir, recur);
  1185.         UnLock(srcdir);
  1186.         UnLock(destdir);
  1187.         if (ierr) break;
  1188.         }
  1189.     else {        /* FILE to DIR,   FILE to FILE   */
  1190.         BPTR destdir, srcdir, tmp;
  1191.         char *destfilename;
  1192.  
  1193.         srcdir = (BPTR)(Myprocess->pr_CurrentDir);
  1194.  
  1195.         if ((tmp = Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)) {
  1196.             if (tmp) UnLock(tmp);
  1197.             ierr = 205;
  1198.             errstr = av[i];
  1199.             goto done;
  1200.             }
  1201.         UnLock(tmp);
  1202.         if (destisdir) {
  1203.             destdir = Lock(destname, ACCESS_READ);
  1204.             destfilename = fib->fib_FileName;
  1205.             }
  1206.         else {
  1207.             destdir = srcdir;
  1208.             destfilename = destname;
  1209.             }
  1210.         printf(" %s..",av[i]);
  1211.         fflush(stdout);
  1212.         ierr = copyfile(av[i], srcdir, destfilename, destdir);
  1213.         if (destisdir) UnLock(destdir);
  1214.         if (ierr) break;
  1215.         }
  1216.     }
  1217.  
  1218. done:
  1219.  
  1220. FreeMem(fib, (long)sizeof(FIB));
  1221. if (ierr) {
  1222.     ierror(errstr, ierr);
  1223.     return(20);
  1224.     }
  1225. return 0;
  1226. }
  1227.  
  1228.  
  1229. copydir(srcdir, destdir, recur)
  1230. register BPTR srcdir, destdir;
  1231. {
  1232.    BPTR cwd;
  1233.    register FIB *srcfib;
  1234.    register BPTR destlock, srclock;
  1235.    int ierr;
  1236.    static int level;
  1237.  
  1238.    level++;
  1239.    ierr = 0;
  1240.    srcfib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  1241.    if (Examine(srcdir, srcfib)) {
  1242.       while (ExNext(srcdir, srcfib)) {
  1243.          if (CHECKBREAK())
  1244.             break;
  1245.          if (srcfib->fib_DirEntryType < 0) {
  1246.             printf("%*s%s..",(level-1) * 6," ",srcfib->fib_FileName);
  1247.             fflush(stdout);
  1248.             ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir);
  1249.             if (ierr)
  1250.                break;
  1251.          } else {
  1252.             if (recur) {
  1253.                cwd = CurrentDir(srcdir);
  1254.                if (srclock = Lock(srcfib->fib_FileName, ACCESS_READ)) {
  1255.                   CurrentDir(destdir);
  1256.                   if (!(destlock = Lock(srcfib->fib_FileName))) {
  1257.                      destlock = CreateDir(srcfib->fib_FileName);
  1258.                      printf("%*s%s (Dir)....[Created]\n",(level-1) * 6,
  1259.                                 " ",srcfib->fib_FileName);
  1260.  
  1261.                         /* UnLock and re Lock if newly created
  1262.                            for file_date() to work properly
  1263.                         */
  1264.                      if (destlock) UnLock(destlock);
  1265.                      destlock = Lock(srcfib->fib_FileName);
  1266.                   }
  1267.                   else
  1268.                      printf("%*s%s (Dir)\n",(level-1) * 6," ",srcfib->fib_FileName);
  1269.                   if (destlock) {
  1270.                      ierr = copydir(srclock, destlock, recur);
  1271.                      UnLock(destlock);
  1272.                   } else {
  1273.                      ierr = (int)((long)IoErr());
  1274.                   }
  1275.                   UnLock(srclock);
  1276.                } else {
  1277.                   ierr = (int)((long)IoErr());
  1278.                }
  1279.                CurrentDir(cwd);
  1280.                if (ierr)
  1281.                   break;
  1282.             }
  1283.          }
  1284.       }
  1285.    } else {
  1286.       ierr = (int)((long)IoErr());
  1287.    }
  1288.    --level;
  1289.    FreeMem(srcfib, (long)sizeof(FIB));
  1290.    return(ierr);
  1291. }
  1292.  
  1293.  
  1294. copyfile(srcname, srcdir, destname, destdir)
  1295. char *srcname, *destname;
  1296. BPTR srcdir, destdir;
  1297. {
  1298. BPTR cwd;
  1299. BPTR f1, f2;
  1300. long i;
  1301. int stat,ierr;
  1302. char *buf;
  1303. struct DPTR *dp, *dps = NULL;
  1304.  
  1305. if ((buf = (char *)AllocMem(8192L, MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  1306.     { ierr = 103; goto fail; }
  1307. ierr = 0;
  1308. cwd = CurrentDir(srcdir);
  1309. if ((f1=Open(srcname, MODE_OLDFILE))==NULL)
  1310.     { errstr = srcname; ierr = 205; goto fail; }
  1311. dps = dopen(srcname,&stat);
  1312. CurrentDir(destdir);
  1313. if (cp_update)
  1314.     {
  1315.     dp=dopen(destname, &stat);
  1316.     if ( dptrtosecs(dp) >= dptrtosecs(dps) &&
  1317.         !strcmp(dps->fib->fib_FileName, dp->fib->fib_FileName))
  1318.         { dclose(dp); Close(f1); printf("..not newer\n"); goto fail; }
  1319.     dclose(dp);
  1320.     }
  1321. if ((f2=Open(destname, MODE_NEWFILE))==NULL)
  1322.     { Close(f1); ierr = (int)((long)IoErr()); errstr=destname; goto fail;  }
  1323. while (i = Read(f1, buf, 8192L))
  1324.     if (Write(f2, buf, i) != i) { ierr = (int)((long)IoErr()); break; }
  1325. Close(f2);
  1326. Close(f1);
  1327. if (!ierr)
  1328.     {
  1329.     if (cp_date) file_date(&dps->fib->fib_Date, destname);
  1330.     printf("..copied\n");
  1331.     }
  1332. else DeleteFile(destname);
  1333. fail:
  1334.  dclose(dps);
  1335.  if (buf) FreeMem(buf, 8192L);
  1336.  CurrentDir(cwd);
  1337.  return(ierr);
  1338. }
  1339.  
  1340. do_touch()
  1341. {
  1342. struct DateStamp ds;
  1343. register unsigned int i;
  1344. DateStamp(&ds);
  1345. for (i=1; i<ac; i++) if (file_date(&ds, av[i])) ierror(av[i],500);
  1346. }
  1347.  
  1348. file_date(date,name)
  1349. struct DateStamp *date;
  1350. char *name;
  1351. {
  1352. long packargs[7];
  1353. UBYTE *ptr;
  1354. struct MsgPort *task;
  1355. BPTR dirlock;
  1356. struct DPTR *tmp;
  1357. int stat;
  1358.  
  1359. if (!(task = (struct MsgPort *)DeviceProc(name))) return(1);
  1360. if (tmp = dopen(name, &stat)) {
  1361.     dirlock = ParentDir(tmp->lock);
  1362.     ptr=AllocMem(65L,MEMF_PUBLIC);
  1363.     CtoBStr(tmp->fib->fib_FileName,(ULONG)ptr >> 2L,64L);
  1364.     dclose(tmp);
  1365.     packargs[1]=dirlock;
  1366.     packargs[2]=(ULONG)ptr >> 2L;
  1367.     packargs[3]=(long)date;
  1368.     SendPacket(ACTION_SET_DATE,packargs,task);
  1369.     UnLock(dirlock);
  1370.     FreeMem(ptr,65L);
  1371.     }
  1372. return 0;
  1373. }
  1374.  
  1375. do_addbuffers()
  1376. {
  1377. long packargs[7];
  1378. long n;
  1379. struct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
  1380.  
  1381. if (!task) { ierror(av[1],510); return 20; }
  1382. Errno=0;
  1383. n=myatol(av[2]);
  1384. if (Errno) return 20;
  1385. packargs[0]=n;
  1386. SendPacket(ACTION_MORE_CACHE,packargs,task);
  1387. return 0;
  1388. }
  1389.  
  1390. do_relabel()
  1391. {
  1392. long packargs[7];
  1393. UBYTE *ptr;
  1394. long n;
  1395. struct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
  1396.  
  1397. if (!task) { ierror(av[1],510); return 20; }
  1398. ptr=AllocMem(65L,MEMF_PUBLIC);
  1399. CtoBStr(av[2],(ULONG)ptr >> 2L,64L);
  1400. packargs[0]=(ULONG)ptr >> 2L;
  1401. SendPacket(ACTION_RENAME_DISK,packargs,task);
  1402. FreeMem(ptr,65L);
  1403. changedisk(task);
  1404. return 0;
  1405. }
  1406.  
  1407. do_diskchange()
  1408. {
  1409. struct MsgPort *task=(struct MsgPort *)DeviceProc(av[1]);
  1410.  
  1411. if (!task) { ierror(av[1],510); return 20; }
  1412. changedisk(task);
  1413. return 0;
  1414. }
  1415.  
  1416. changedisk(task)
  1417. struct MsgPort *task;
  1418. {
  1419. long packargs[7];
  1420.  
  1421. packargs[0]=1L;
  1422. SendPacket(ACTION_INHIBIT,packargs,task);
  1423. packargs[0]=0L;
  1424. SendPacket(ACTION_INHIBIT,packargs,task);
  1425. }
  1426. SHAR_EOF
  1427. cat << \SHAR_EOF > comm3.c
  1428. /*
  1429.  * COMM3.C
  1430.  *
  1431.  * Version 3.01A by Carlo Borreo & Cesare Dieni 17-Nov-88
  1432.  *
  1433.  */
  1434.  
  1435. do_assign() {
  1436. switch(ac) {
  1437.     case 1:  assignlist();
  1438.          break;
  1439.     case 2:  doassign(av[1], NULL);
  1440.          break;
  1441.     case 3:  doassign(av[1], av[2]);
  1442.          break;
  1443.     default: ierror(NULL, 500);
  1444.          break;
  1445.     }
  1446. return 0;
  1447. }
  1448.  
  1449. char *assign_errors[4]={
  1450.     "",
  1451.     "Name %s is not valid\n",
  1452.     "Weird error\n",
  1453.     "Can't cancel %s\n"
  1454.     };
  1455.  
  1456. doassign(log, phy)
  1457. char *log, *phy;
  1458. {
  1459. int last=strlen(log) - 1;
  1460.  
  1461. if (log[last] != ':') fprintf(stderr, "Bad name %s\n", log);
  1462. else {
  1463.     log[last] = 0;
  1464.     fprintf(stderr,assign_errors[Assign(log, phy)],log);
  1465.     }
  1466. }
  1467.  
  1468. assignlist()
  1469. {
  1470. struct DirectoryEntry *de_head=NULL, *de;
  1471. char buf[256];
  1472. BPTR lock;
  1473. int ctr=0;
  1474.  
  1475. AddDADevs(&de_head, DLF_DEVICES | DLF_VOLUMES | DLF_DIRS);
  1476. printf("Devices:\n");
  1477. for (de=de_head; de && de->de_Type==DLX_DEVICE; de=de->de_Next) {
  1478.     printf("%-8s",de->de_Name);
  1479.     if (ctr++ == 5) { ctr=0; printf("\n"); }
  1480.     }
  1481. printf("\n\nVolumes:\n");
  1482. for (    ;
  1483.     de && (de->de_Type==DLX_VOLUME || de->de_Type==DLX_UNMOUNTED);
  1484.     de=de->de_Next
  1485.     )
  1486.     printf( "%-16s %s\n",
  1487.         de->de_Name,
  1488.         de->de_Type == DLX_VOLUME ? "[Mounted]" : ""
  1489.         );
  1490. printf("\nDirectories:\n");
  1491. for (; de && de->de_Type==DLX_ASSIGN; de=de->de_Next) {
  1492.     if (lock=Lock(de->de_Name, ACCESS_READ)) {
  1493.         PathName(lock, buf, 256L);
  1494.         UnLock(lock);
  1495.         }
  1496.     else
  1497.         strcpy(buf,"Unexisting lock");
  1498.     printf("%-20s%s\n",de->de_Name,buf);
  1499.     }
  1500. FreeDAList(&de_head);
  1501. }
  1502.  
  1503. do_join()
  1504. {
  1505. BPTR sou, dest;
  1506. char *buffer;
  1507. unsigned int i;
  1508. long n;
  1509. char *namedest=av[--ac];
  1510.  
  1511. get_opt("r", &i);
  1512. if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  1513. if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  1514. if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  1515.     { pError(namedest); goto fail1; }
  1516. for (i=1; i<ac; i++) {
  1517.     if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  1518.     else
  1519.         while( (n=Read(sou, buffer, 8192L)) > 0 )
  1520.             if (Write(dest, buffer, n) != n)
  1521.                 { pError(namedest); Close(sou); goto fail2; }
  1522.     Close(sou);
  1523.     }
  1524. fail2:
  1525.     Close(dest);
  1526. fail1:
  1527.     free(buffer);
  1528.     return 0;
  1529. }
  1530.  
  1531. #define BUFDIM 512L
  1532. #define MAXSTR 256
  1533.  
  1534. int minstr;
  1535.  
  1536. strings_in_file(s)
  1537. char *s;
  1538. {
  1539. char c;
  1540. char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  1541. register unsigned int i, strctr=0;
  1542. BPTR fh;
  1543. int out, n;
  1544.  
  1545. if ( fh=Open(s, MODE_OLDFILE) ) {
  1546.     fprintf(stderr, "Strings in %s (len>=%d):\n",s,minstr);
  1547.     while ( (n=(int)Read(fh, readbuf, BUFDIM)) > 0 && !CHECKBREAK() )
  1548.         for (i=0; i<n; i++) {
  1549.         c=readbuf[i];
  1550.         if (c<0x20 || c>0x7f) {
  1551.             out=(strctr>=minstr);
  1552.             if (!out) strctr=0;
  1553.             }
  1554.         else {
  1555.             strbuf[strctr++]=c;
  1556.             out=(strctr>=BUFDIM);
  1557.             }
  1558.         if (out) {
  1559.             strbuf[strctr]='\0';
  1560.             puts(strbuf);
  1561.             strctr=0;
  1562.             }
  1563.         }
  1564.     Close(fh);
  1565.     }
  1566. else pError(s);
  1567. }
  1568.  
  1569. do_strings()
  1570. {
  1571. minstr=(int)myatol(av[--ac]);
  1572. all_args("r", strings_in_file, 0);
  1573. return 0;
  1574. }
  1575.  
  1576. BPTR myfile[MAXMYFILES];
  1577.  
  1578. do_open()
  1579. {
  1580. long mode;
  1581. unsigned int n;
  1582.  
  1583. switch (av[2][0]) {
  1584.     case 'r': mode=MODE_OLDFILE; break;
  1585.     case 'w': mode=MODE_NEWFILE; break;
  1586.     default : ierror(NULL,500); return;
  1587.     }
  1588. Errno=0;
  1589. n=(unsigned int)myatol(av[3]);
  1590. if (Errno) return 20;
  1591. if (n<0 || n>MAXMYFILES) { ierror(av[3],500); return 20; }
  1592. myfile[n]=Open(av[1],mode);
  1593. return (myfile[n]==NULL);
  1594. }
  1595.  
  1596. do_close()
  1597. {
  1598. register unsigned int i;
  1599. int n;
  1600.  
  1601. for (i=1; i<ac; i++) {
  1602.     Errno=0;
  1603.     n=(int)myatol(av[i]);
  1604.     if (Errno) return 20;
  1605.     if (n<0 || n>MAXMYFILES) { ierror(av[i],500); return 20; }
  1606.     myclose(n);
  1607.     }
  1608. return 0;
  1609. }
  1610.  
  1611. myclose(n)
  1612. {
  1613. if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  1614. }
  1615.  
  1616. do_fileslist()
  1617. {
  1618. register unsigned short i;
  1619. int flag=0;
  1620.  
  1621. printf("Open files:");
  1622. for (i=0; i<MAXMYFILES; i++)
  1623.     if (myfile[i]) { printf(" %d",i); flag=1; }
  1624. if (!flag) printf(" None!");
  1625. printf("\n");
  1626. }
  1627.  
  1628. BPTR extOpen(name,mode)
  1629. char *name;
  1630. long mode;
  1631. {
  1632. if (name[0]=='.') return myfile[atoi(name+1)];
  1633. return Open(name,mode);
  1634. }
  1635.  
  1636. extClose(fh)
  1637. BPTR fh;
  1638. {
  1639. register unsigned short i;
  1640.  
  1641. for (i=0; i<MAXMYFILES; i++)
  1642.     if (myfile[i]==fh) return;
  1643. Close(fh);
  1644. }
  1645.  
  1646. do_resident(avline)
  1647. char *avline;
  1648. {
  1649. unsigned int i;
  1650. BPTR seg;
  1651. struct ResidentPrgNode *p;
  1652. char *args;
  1653.  
  1654. get_opt("ar", &i);
  1655. switch (options) {
  1656.     case 0:
  1657.     ObtainSemaphore (& (ArpBase->ResPrgProtection) );
  1658.     if (p=ArpBase->ResidentPrgList) {
  1659.         printf("Name             Users\n");
  1660.         for (; p; p=p->rpn_Next)
  1661.             printf("%-16s %-3ld\n",p->rpn_Name,p->rpn_Usage);
  1662.         }
  1663.     else printf("No resident program(s)\n");
  1664.     ReleaseSemaphore(& (ArpBase->ResPrgProtection) );
  1665.     break;
  1666.     case 1:
  1667.     for (; i<ac; i++)
  1668.         if ( (seg=(BPTR)LoadPrg(av[i])) && AddResidentPrg(seg,av[i]) )
  1669.             printf("OK! %s is now resident\n", BaseName(av[i]));
  1670.         else pError(av[i]);
  1671.     break;
  1672.     case 2:
  1673.     for (; i<ac; i++)
  1674.         if (RemResidentPrg(av[i])) ierror(av[i],202);
  1675.         else printf("Removed %s\n",av[i]);
  1676.     break;
  1677.     default:
  1678.     ierror(NULL,500);
  1679.     break;
  1680.     }
  1681. }
  1682.  
  1683. struct ProcessControlBlock pcb={
  1684.     4000,        /* pcb_StackSize    */
  1685.     0,        /* pcb_Pri        */
  1686.     };
  1687. /* remaining field are NULL */
  1688.     
  1689. do_truerun(avline, backflag)
  1690. char *avline;
  1691. {
  1692. char name[200];
  1693. char *FindIt();
  1694.  
  1695. if (backflag) {
  1696.     pcb.pcb_Control=NULL;
  1697.     pcb.pcb_Input=pcb.p_Output=Open("NIL:",MODE_OLDFILE);
  1698.     }
  1699. else {
  1700.     pcb.pcb_Control=PRB_SAVEIO;
  1701.     pcb.pcb_Input=pcb.p_Output =NULL;
  1702.     }
  1703. if (FindIt(av[1], "", name))
  1704.     ASyncRun(name,next_word(next_word(avline)),&pcb);
  1705. else
  1706.     ierror(av[1],205);
  1707. return 0;
  1708. }
  1709.  
  1710. int exists(name)
  1711. char *name;
  1712. {
  1713. BPTR lock;
  1714.  
  1715. if (lock=Lock(name,ACCESS_READ)) {
  1716.     UnLock(lock);
  1717.     return 1;
  1718.     }
  1719. return 0;
  1720. }
  1721.  
  1722. do_aset()
  1723. {
  1724. Setenv(av[1],av[2]);
  1725. return 0;
  1726. }
  1727.  
  1728. #define HTYPELINE 16L
  1729.  
  1730. htype_a_file(s)
  1731. char *s;
  1732. {
  1733. BPTR fh;
  1734. long n, filesize=0;
  1735. char buf[HTYPELINE+1];
  1736. register unsigned int i;
  1737.  
  1738. if ( (fh=Open(s,MODE_OLDFILE))==NULL ) { pError(s); return 20; }
  1739. while ( (n=Read(fh,buf,HTYPELINE))>0 && !dobreak()) {
  1740.     printf("%06lx: ",filesize);
  1741.     filesize+=n;
  1742.     for (i=0; i<n; i++) {
  1743.         printf( (i&3) ? "%02x" : " %02x",(int)(unsigned char)buf[i]);
  1744.         if (buf[i]<=0x20) buf[i]='.';
  1745.         }
  1746.     for ( ; i<HTYPELINE; i++) printf( (i&3) ? "  " : "   ");
  1747.     buf[i]=0;
  1748.     printf("    %s\n",buf);
  1749.     }
  1750. Close(fh);
  1751. return 0;
  1752. }
  1753.  
  1754. do_htype()
  1755. {
  1756. all_args("", htype_a_file, 0);
  1757. return 0;
  1758. }
  1759.  
  1760. do_stack()
  1761. {
  1762. long n;
  1763.  
  1764. if (ac>1) {
  1765.     n=myatol(av[1]);
  1766.     if (!Errno) Mycli->cli_DefaultStack=(long)(n >> 2L);
  1767.     }
  1768. else printf("current stack size is %ld bytes\n",
  1769.                 (long)Mycli->cli_DefaultStack << 2L);
  1770. }
  1771.  
  1772. long myatol(s)
  1773. char *s;
  1774. {
  1775. long n;
  1776.  
  1777. Errno=0;
  1778. n=Atol(s);
  1779. if (Errno==ERRBADINT) ierror(s,511);
  1780. else Errno=0;
  1781. return n;
  1782. }
  1783.  
  1784. do_fault()
  1785. {
  1786. struct PERROR *p;
  1787. register unsigned int i;
  1788. int n;
  1789.  
  1790. for (i=1; i<ac; i++) {
  1791.     n=(int)myatol(av[i]);
  1792.     if (!Errno) {
  1793.         for (p=Perror; p->errnum && p->errnum!=n; p++);
  1794.         if (p->errnum)
  1795.             printf("Fault %d: %s\n",n,p->errstr);
  1796.         else
  1797.             printf("Fault %d not recognized\n",n);
  1798.         }
  1799.     }
  1800. return 0;
  1801. }
  1802.  
  1803. struct rpncommand {
  1804.     char *str;
  1805.     int parsin, parsout;
  1806.     };
  1807.  
  1808. struct rpncommand rpn[]={
  1809.     "+",    2,    1,
  1810.     "-",    2,    1,
  1811.     "*",    2,    1,
  1812.     "/",    2,    1,
  1813.     "%",    2,    1,
  1814.     "&",    2,    1,
  1815.     "|",    2,    1,
  1816.     "~",    1,    1,
  1817.     ">",    2,    1,
  1818.     "<",    2,    1,
  1819.     "==",    2,    1,
  1820.     "!",    1,    1,
  1821.     ".",    1,    0,
  1822.     "CR",    0,    0,
  1823.     "EXISTS", 1,    1,
  1824.     "STR",    0,    1,
  1825.     "PRINT",1,    0,
  1826.     "$",    1,    1,
  1827.     "HELP",    0,    0,
  1828.     "LEN",    1,    1,
  1829.     "STRCMP", 2,    1,
  1830.     "[]",    2,    1,
  1831.     "SETVAR", 2,    0,
  1832.     "DUP",    1,    2,
  1833.     "DROP",    1,    0,
  1834.     "SWAP",    2,    2,
  1835.     "ATOL",    1,    1,
  1836.     NULL,    0,    1,    /* this looks for a number */
  1837. };
  1838.  
  1839. do_rpn(garbage,ifflag) /* ifflag!=0 if called from if */
  1840. char *garbage;
  1841. {
  1842. register long n0, n1;
  1843. long t;
  1844. unsigned int i, j;
  1845. int sp=0;
  1846. long stack[100];
  1847. struct rpncommand *temp;
  1848.  
  1849. i=1;
  1850. if (ifflag) get_opt("rn",&i);
  1851. for (; i<ac; i++) {
  1852.     for (j=0; rpn[j].str && Strcmp(rpn[j].str,av[i]); j++) ;
  1853.     n0=stack[sp-1];
  1854.     n1=stack[sp-2];
  1855.     sp -= (rpn[j].parsin);
  1856.     if (sp<0) { fprintf(stderr, "Empty stack\n"); return 1; }
  1857.     switch (j) {
  1858.       case 0:    n0 += n1;        break;
  1859.       case 1:    n0 = n1-n0;        break;
  1860.       case 2:    n0 *= n1;        break;
  1861.       case 3:    n0 = n1/n0;        break;
  1862.       case 4:    n0 %= n1;        break;
  1863.       case 5:    n0 &= n1;        break;
  1864.       case 6:    n0 |= n1;        break;
  1865.       case 7:    n0 =  ~n0;        break;
  1866.       case 8:    n0 = (n1 > n0);        break;
  1867.       case 9:    n0 = (n1 < n0);        break;
  1868.       case 10:    n0 = (n0 == n1);    break;
  1869.       case 11:    n0 = !n0;        break;
  1870.       case 12:    printf("%ld", n0);    break;
  1871.       case 13:    printf("\n");        break;
  1872.       case 14:    n0=exists(n0);        break;
  1873.       case 15:    n0=(long)av[++i];
  1874.             if (i==ac) { ierror(av[i-1],500); return 20; }
  1875.             break;
  1876.       case 16:    printf("%s",n0);    break;
  1877.       case 17:    n0=(long)get_var(LEVEL_SET,n0); break;
  1878.       case 18:    printf("In Commands Out\n");
  1879.             for (temp=rpn; temp->str; temp++)
  1880.                 printf(" %d %-10s%d\n",
  1881.                 temp->parsin,temp->str,temp->parsout);
  1882.             break;
  1883.       case 19:    n0=(long)strlen(n0);    break;
  1884.       case 20:    n0=(long)strcmp(n0,n1); break;
  1885.       case 21:    n0=*((char *)(n0+n1));    break;
  1886.       case 22:    set_var(LEVEL_SET,n1,n0); break;
  1887.       case 23:    n1=n0;            break;
  1888.       case 24:    t=n0; n0=n1; n1=t;    break;
  1889.       case 25:                break;
  1890.       case 26:    n0=atol(n0);        break;
  1891.       default:    n0=myatol(av[i]);
  1892.             if (Errno) ierror(av[i],500);
  1893.             break;
  1894.       }
  1895.     stack[sp]=n0;
  1896.     stack[sp+1]=n1;
  1897.     sp += rpn[j].parsout;
  1898.     }
  1899. if (!ifflag) for (i=0;i<sp;i++) printf("stack[%d]: %ld\n", i, stack[i]);
  1900. return (sp>0 ? (int)stack[sp-1] : 0);
  1901. }
  1902.  
  1903. do_path()
  1904. {
  1905. union {    long *lp; long ll; } l;
  1906. BPTR lock;
  1907. char buf[256];
  1908.  
  1909. puts("Current dir");
  1910. l.lp = (long *) Mycli->cli_CommandDir;
  1911. while (l.ll) {
  1912.     l.ll <<= 2;
  1913.     PathName(l.lp[1], buf, 256L);
  1914.     puts(buf);
  1915.     l.ll = *l.lp;
  1916.     }
  1917. puts("C:");
  1918. return 0;
  1919. }
  1920.  
  1921. do_pri()
  1922. {
  1923. long t, pri;
  1924.  
  1925. t=myatol(av[1]);
  1926. if (Errno) return 20;
  1927. if (t<1 || t>20) { ierror(av[1],500); return 20; }
  1928. pri=myatol(av[2]);
  1929. if (Errno) return 20;
  1930. if (pri<-128 || t>127) { ierror(av[2],500); return 20; }
  1931. Forbid();
  1932. SetTaskPri(FindCLI(t),pri);
  1933. return 0;
  1934. }
  1935. SHAR_EOF
  1936. cat << \SHAR_EOF > execom.c
  1937. /*
  1938.  * EXECOM.C
  1939.  *
  1940.  * Matthew Dillon, 10 August 1986
  1941.  *    Finally re-written.
  1942.  *
  1943.  * Version 2.07M by Steve Drew 10-Sep-87
  1944.  *
  1945.  * Version 3.01A by Carlo Borreo & Cesare Dieni 17-Nov-88
  1946.  *
  1947.  */
  1948.  
  1949. extern char *v_histnum, *v_except;
  1950.  
  1951. #define F_EXACT 0
  1952. #define F_ABBR  1
  1953.  
  1954. #define ST_COND   0x01
  1955. #define ST_NORED  0x02
  1956. #define ST_NOEXP  0x04
  1957. #define ST_AV     0x08 /* delimit args within a variable */
  1958.  
  1959. int has_wild = 0;                 /* set if any arg has wild card */
  1960.  
  1961. struct COMMAND {
  1962.     int (*func)();
  1963.     short minargs;
  1964.     short stat;
  1965.     int val;
  1966.     char *name;
  1967. };
  1968.  
  1969. extern char *format_insert_string();
  1970. extern char *mpush(), *exarg();
  1971.  
  1972. extern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri();
  1973. extern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany();
  1974. extern int do_open(), do_close(), do_fileslist(), do_htype();
  1975. extern int do_run(), do_number(), do_assign(), do_join();
  1976. extern int do_quit(), do_set_var(), do_unset_var();
  1977. extern int do_echo(), do_source(), do_mv(), do_addbuffers();
  1978. extern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history();
  1979. extern int do_mem(), do_cat(), do_dir(), do_info(), do_inc();
  1980. extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
  1981. extern int do_input(), do_ver(), do_sleep(), do_help();
  1982. extern int do_strhead(), do_strtail(), do_relabel();
  1983. extern int do_copy(), date(), do_protect(), do_ps();
  1984. extern int do_forever(), do_abortline(), do_strings(), do_touch();
  1985. extern int do_window(), do_search(), do_filenote();
  1986. char *push_cpy();
  1987.  
  1988. static struct COMMAND Command[] = {
  1989. do_run,        0, ST_AV,    0,    "\001",   /* may call do_source */
  1990. do_set_var,    0, 0, LEVEL_ALIAS,    "alias",  /* uses avline */
  1991. do_abortline,    0, 0,        0,    "abortline",
  1992. do_addbuffers,    2, 0,        0,    "addbuffers",
  1993. do_aset,    1, 0,        0,    "aset",
  1994. do_assign,    0, 0,        0,    "assign",
  1995. do_cat,        0, 0,        0,    "cat",
  1996. do_cd,        0, 0,        0,    "cd",
  1997. do_close,    0, 0,        0,    "close",
  1998. do_copy,    1, 0,        0,    "copy",
  1999. do_copy,    1, 0,        0,    "cp",
  2000. date,        0, 0,        0,    "date",
  2001. do_rm,        0, 0,        0,    "delete",
  2002. do_dir,        0, ST_NOEXP,    0,    "dir",
  2003. do_diskchange,    1, 0,        0,    "diskchange",
  2004. do_inc,        1, 0,        -1,    "dec",
  2005. do_echo,    0, 0,        0,    "echo", /* uses avline */
  2006. do_if,        0, ST_COND,    1,    "else",
  2007. do_if,        0, ST_COND,    2,    "endif",
  2008. do_fault,    1, 0,        0,    "fault",
  2009. do_filenote,    2, 0,        0,    "filenote",
  2010. do_fileslist,    0, 0,        0,    "flist",
  2011. do_foreach,    3, ST_NORED,    0,    "foreach",
  2012. do_forever,    1, ST_NORED,    0,    "forever",
  2013. do_goto,    1, 0,        0,    "goto",
  2014. do_help,    0, 0,        0,    "help",
  2015. do_history,    0, 0,        0,    "history",
  2016. do_howmany,    0, 0,        0,    "howmany",
  2017. do_htype,    1, 0,        0,    "htype",
  2018. do_if,        1, ST_COND|ST_NORED,0,    "if",
  2019. do_inc,        1, 0,        1,    "inc",
  2020. do_info,    0, 0,        0,    "info",
  2021. do_join,    2, 0,        1,    "join",
  2022. do_input,    1, 0,        0,    "input",
  2023. do_label,    1, ST_COND,    0,    "label",
  2024. do_dir,        0, ST_NOEXP,    0,    "ls",
  2025. do_mkdir,    0, 0,        0,    "md",
  2026. do_mem ,    0, 0,        0,    "mem",
  2027. do_mkdir,    0, 0,        0,    "mkdir",
  2028. do_mv,        2, 0,        0,    "mv",
  2029. do_open,    3, 0,        0,    "open",
  2030. do_path,    0, 0,        0,    "path",
  2031. do_pri,        2, 0,        0,    "pri",
  2032. do_protect,    2, 0,        0,    "protect",
  2033. do_ps,        0, 0,        0,    "ps",
  2034. do_pwd,        0, 0,        0,    "pwd",
  2035. do_quit,    0, ST_NORED,    0,    "quit",
  2036. do_truerun,    1, ST_NORED,    1,    "rback",
  2037. do_mv,        2, 0,        0,    "rename",
  2038. do_relabel,    2, 0,        0,    "relabel",
  2039. do_resident,    0, 0,        0,    "resident",
  2040. do_return,    0, 0,        0,    "return",
  2041. do_rm,        0, 0,        0,    "rm",
  2042. do_rpn,        0, ST_NOEXP|ST_NORED,0,    "rpn",
  2043. do_truerun,    1, ST_NORED,    0,    "run",
  2044. do_search,    2, 0,        0,    "search",
  2045. do_set_var,    0, ST_AV, LEVEL_SET,    "set",
  2046. do_sleep,    0, 0,        0,    "sleep",
  2047. do_source,    0, ST_NORED|ST_AV, 0,    "source", /* uses avline */
  2048. do_stack,    0, 0,        0,    "stack",
  2049. do_strhead,    3, 0,        0,    "strhead",
  2050. do_strings,    1, 0,        0,    "strings",
  2051. do_strtail,    3, 0,        0,    "strtail",
  2052. do_touch,    0, 0,        0,    "touch",
  2053. do_cat,        0, 0,        0,    "type",
  2054. do_unset_var,    0, 0, LEVEL_ALIAS,    "unalias",
  2055. do_unset_var,    0, 0, LEVEL_SET  ,    "unset",
  2056. do_ver,        0, 0,        0,    "version",
  2057. do_window,    0, ST_NOEXP,    0,    "window",
  2058. '\0',        0, 0,        0,    NULL
  2059. };
  2060.  
  2061. static unsigned char elast;        /* last end delimeter */
  2062. static char Cin_ispipe, Cout_ispipe;
  2063.  
  2064. exec_command(base)
  2065. char *base;
  2066. {
  2067. register char *scr;
  2068. char buf[32];
  2069.  
  2070. if (!H_stack) {
  2071.     add_history(base);
  2072.     sprintf(buf, "%d", H_tail_base + H_len);
  2073.     set_var(LEVEL_SET, v_histnum, buf);
  2074.     }
  2075. scr = malloc((strlen(base) << 2) + 2);
  2076. preformat(base, scr);
  2077. return (fcomm(scr, 1) ? -1 : 1);
  2078. }
  2079.  
  2080. isalphanum(c)
  2081. register char c;
  2082. {
  2083. return (
  2084.     (c >= '0' && c <= '9') ||
  2085.     (c >= 'a' && c <= 'z') ||
  2086.     (c >= 'A' && c <= 'Z') ||
  2087.     (c == '_')
  2088.     );
  2089. }
  2090.  
  2091. preformat(s, d)
  2092. register char *s, *d;
  2093. {
  2094. register int si, di, qm;
  2095.  
  2096. si = di = qm = 0;
  2097. while (s[si] == ' ' || s[si] == 9) ++si;
  2098. while (s[si]) {
  2099.     if (qm && s[si] != '\"' && s[si] != '\\') {
  2100.         d[di++] = s[si++] | 0x80;
  2101.         continue;
  2102.         }
  2103.     switch (s[si]) {
  2104.         case ' ':
  2105.         case 9:
  2106.             d[di++] = ' ';
  2107.             while (s[si] == ' ' || s[si] == 9) ++si;
  2108.             if (s[si] == 0 || s[si] == '|' || s[si] == ';') --di;
  2109.             break;
  2110.         case '*':
  2111.         case '?':
  2112.             d[di++] = 0x80;
  2113.         case '!':
  2114.             d[di++] = s[si++];
  2115.             break;
  2116.         case '#':
  2117.             d[di++] = '\0';
  2118.             while (s[si]) ++si;
  2119.             break;
  2120.         case ';':
  2121.         case '|':
  2122.             d[di++] = s[si++];
  2123.             while (s[si] == ' ' || s[si] == 9) ++si;
  2124.             break;
  2125.         case '\\':
  2126.             d[di++] = s[++si] | 0x80;
  2127.             if (s[si]) ++si;
  2128.             break;
  2129.         case '\"':
  2130.             qm = 1 - qm;
  2131.             ++si;
  2132.             break;
  2133.         case '^':
  2134.             d[di++] = s[++si] & 0x1F;
  2135.             if (s[si]) ++si;
  2136.             break;
  2137.         case '$': /* search end of var name and place false space */
  2138.             d[di++] = 0x80;
  2139.             d[di++] = s[si++];
  2140.             while (isalphanum(s[si])) d[di++] = s[si++];
  2141.             d[di++] = 0x80;
  2142.             break;
  2143.         default:
  2144.             d[di++] = s[si++];
  2145.             break;
  2146.         }
  2147.     }
  2148. d[di++]=0;
  2149. d[di]=0;
  2150. if (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
  2151. }
  2152.  
  2153. extern BPTR extOpen();
  2154.  
  2155. /*
  2156.  * process formatted string.  ' ' is the delimeter.
  2157.  *
  2158.  *    0: check '\0': no more, stop, done.
  2159.  *    1: check $.     if so, extract, format, insert
  2160.  *    2: check alias. if so, extract, format, insert. goto 1
  2161.  *    3: check history or substitution, extract, format, insert. goto 1
  2162.  *
  2163.  *    4: assume first element now internal or disk based command.
  2164.  *
  2165.  *    5: extract each ' ' or 0x80 delimited argument and process, placing
  2166.  *       in av[] list (except 0x80 args appended).  check in order:
  2167.  *
  2168.  *             '$'         insert string straight
  2169.  *             '>'         setup stdout
  2170.  *             '>>'        setup stdout flag for append
  2171.  *             '<'         setup stdin
  2172.  *             '*' or '?'  do directory search and insert as separate args.
  2173.  *
  2174.  *             ';' 0 '|'   end of command.  if '|' setup stdout
  2175.  *                          -execute command, fix stdin and out (|) sets
  2176.  *                           up stdin for next guy.
  2177.  */
  2178.  
  2179.  
  2180. fcomm(str, freeok)
  2181. register char *str;
  2182. {
  2183.    static int alias_count;
  2184.    int p_alias_count = 0;
  2185.    char *istr;
  2186.    char *nextstr;
  2187.    char *command;
  2188.    char *pend_alias = NULL;
  2189.    char err = 0;
  2190.    has_wild = 0;
  2191.  
  2192.    ++alias_count;
  2193.  
  2194.    mpush_base();
  2195.    if (*str == 0)
  2196.       goto done1;
  2197. step1:
  2198.    if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
  2199.       fprintf(stderr,"Alias Loop\n");
  2200.       err = 20;
  2201.       goto done1;
  2202.    }
  2203. /*
  2204.    if (str[1] == '$') {
  2205.       if (istr = get_var (LEVEL_SET, str + 2))
  2206.          str = format_insert_string(str, istr, &freeok);
  2207.    }
  2208. */
  2209.    istr = NULL;
  2210.    if (*(unsigned char *)str < 0x80)
  2211.       istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
  2212.    *str &= 0x7F;                          /* remove \ teltail     */
  2213.    if (istr) {
  2214.       if (*istr == '%') {
  2215.          pend_alias = istr;
  2216.       } else {
  2217.          str = format_insert_string(str, istr, &freeok);
  2218.          goto step1;
  2219.       }
  2220.    }
  2221.    if (*str == '!') {
  2222.       char *p, c;                     /* fix to allow !cmd1;!cmd2 */
  2223.       for(p = str; *p && *p != ';' ; ++p);
  2224.       c = *p;
  2225.       *p = '\0';
  2226.       istr = get_history(str);
  2227.       *p = c;
  2228.       replace_head(istr);
  2229.       str = format_insert_string(str, istr, &freeok);
  2230.       goto step1;
  2231.    }
  2232.    nextstr = str;
  2233.    command = exarg(&nextstr);
  2234.    if (*command == 0)
  2235.       goto done0;
  2236.    if (pend_alias == 0) {
  2237.       if (cmd_stat(command) & ST_COND)
  2238.          goto skipgood;
  2239.    }
  2240.    if (disable || forward_goto) {
  2241.       while (elast && elast != ';' && elast != '|')
  2242.          exarg(&nextstr);
  2243.       goto done0;
  2244.    }
  2245. skipgood:
  2246.    {
  2247.       register char *arg, *ptr, *scr;
  2248.       short redir;
  2249.       short doexpand;
  2250.       short cont;
  2251.       short inc;
  2252.  
  2253.       ac = 1;
  2254.       av[0] = command;
  2255. step5:                                          /* ac = nextac */
  2256.       if (!elast || elast == ';' || elast == '|')
  2257.          goto stepdone;
  2258.  
  2259.       av[ac] = '\0';
  2260.       cont = 1;
  2261.       doexpand = redir = inc = 0;
  2262.  
  2263.       while (cont && elast) {
  2264.          int cstat = cmd_stat(command);
  2265.  
  2266.          ptr = exarg(&nextstr);
  2267.          inc = 1;
  2268.          arg = "";
  2269.          cont = (elast == 0x80);
  2270.          switch (*ptr) {
  2271.          case '<':
  2272.             redir = -2;
  2273.          case '>':
  2274.             if (cstat & (ST_NORED | ST_COND)) {
  2275.                                                         /* don't extract   */
  2276.                 redir = 0;                              /* <> stuff if its */
  2277.                 arg = ptr;                              /* external cmd.   */
  2278.                 break;
  2279.             }
  2280.             ++redir;
  2281.             arg = ptr + 1;
  2282.             if (*arg == '>') {
  2283.                redir = 2;        /* append >> */
  2284.                ++arg;
  2285.             }
  2286.             cont = 1;
  2287.             break;
  2288.          case '$':
  2289.             /* restore args if from set command or pend_alias */
  2290.             if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
  2291.                if (cstat & ST_COND) {
  2292.                   char *tp;
  2293.                   tp = push_cpy(arg);
  2294.                   arg = tp;
  2295.                }
  2296.                else {
  2297.                   char *pe, sv, *index();
  2298.                   while (pe = index(arg,0xA0)) {
  2299.                      sv = *pe;
  2300.                      *pe = '\0';
  2301.                      av[ac++] = push_cpy(arg);
  2302.                      *pe = sv;
  2303.                      av[ac] = '\0';
  2304.                      arg = pe+1;
  2305.                   }
  2306.                }
  2307.             }
  2308.             else
  2309.                arg = ptr;
  2310.             break;
  2311.          case '*':
  2312.          case '?':
  2313.             if ((cstat & ST_NOEXP) == 0)
  2314.                doexpand = 1;
  2315.             arg = ptr;
  2316.             break;
  2317.          default:
  2318.             arg = ptr;
  2319.             break;
  2320.          }
  2321.  
  2322.          /* Append arg to av[ac] */
  2323.  
  2324.          for (scr = arg; *scr; ++scr)
  2325.             *scr &= 0x7F;
  2326.          if (av[ac]) {
  2327.             register char *old = av[ac];
  2328.             av[ac] = mpush(strlen(arg)+strlen(av[ac]));
  2329.             strcpy(av[ac], old);
  2330.             strcat(av[ac], arg);
  2331.          } else {
  2332.             av[ac] = push_cpy(arg);
  2333.          }
  2334.          if (elast != 0x80)
  2335.             break;
  2336.       }
  2337.  
  2338.       /* process expansion */
  2339.  
  2340.       if (doexpand) {
  2341.          char **eav, **ebase;
  2342.          int eac;
  2343.          has_wild = 1;
  2344.          eav = ebase = expand(av[ac], &eac);
  2345.          inc = 0;
  2346.          if (eav) {
  2347.             if (ac + eac + 2 > MAXAV) {
  2348.                ierror (NULL, 506);
  2349.                err = 1;
  2350.             } else {
  2351.                QuickSort(eav, eac);
  2352.                for (; eac; --eac, ++eav)
  2353.                   av[ac++] = push_cpy(*eav);
  2354.             }
  2355.             free_expand (ebase);
  2356.          }
  2357.       }
  2358.  
  2359.       /* process redirection  */
  2360.  
  2361.       if (redir && !err) {
  2362.          register char *file = (doexpand) ? av[--ac] : av[ac];
  2363.  
  2364.          if (redir < 0)
  2365.             Cin_name = file;
  2366.          else {
  2367.             Cout_name = file;
  2368.             Cout_append = (redir == 2);
  2369.          }
  2370.          inc = 0;
  2371.       }
  2372.  
  2373.       /* check elast for space */
  2374.  
  2375.       if (inc) {
  2376.          ++ac;
  2377.          if (ac + 2 > MAXAV) {
  2378.             ierror (NULL, 506);
  2379.             err = 1;                /* error condition */
  2380.             elast = 0;              /* don't process any more arguemnts */
  2381.          }
  2382.       }
  2383.       if (elast == ' ')
  2384.          goto step5;
  2385.    }
  2386. stepdone:
  2387.    av[ac] = '\0';
  2388.  
  2389.    /* process pipes via files */
  2390.  
  2391.    if (elast == '|' && !err) {
  2392.       static int which;             /* 0 or 1 in case of multiple pipes */
  2393.       which = 1 - which;
  2394.       Cout_name = (which) ? Pipe1 : Pipe2;
  2395.       Cout_ispipe = 1;
  2396.    }
  2397.  
  2398.  
  2399.    if (err)
  2400.       goto done0;
  2401.  
  2402.    {
  2403.       register int i;
  2404.       char save_elast;
  2405.       char *compile_av();
  2406.       register char *avline;
  2407.       unsigned char delim = ' ';
  2408.  
  2409.       save_elast = elast;
  2410.       if (pend_alias || (cmd_stat(command) & ST_AV))
  2411.          delim = 0xA0;
  2412.       avline = compile_av(av,((pend_alias) ? 1 : 0), ac , delim);
  2413.  
  2414.  
  2415.       if (pend_alias) {                               /* special % alias */
  2416.          register char *ptr, *scr;
  2417.          for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
  2418.          set_var (LEVEL_SET, pend_alias + 1, avline);
  2419.          free (avline);
  2420.  
  2421.          scr = malloc((strlen(ptr) << 2) + 2);
  2422.          preformat (ptr, scr);
  2423.          fcomm (scr, 1);
  2424.          unset_var (LEVEL_SET, pend_alias + 1);
  2425.       } else {                                        /* normal command  */
  2426.          register int ccno;
  2427.          long  oldcin  = Myprocess->pr_CIS;
  2428.          long  oldcout = Myprocess->pr_COS;
  2429.          char *Cin_buf;
  2430.          struct FileHandle *ci;
  2431.          long oldbuf;
  2432.  
  2433.          fflush(stdout);
  2434.          ccno = find_command (command);
  2435.          if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
  2436.             if (Cin_name) {
  2437.                if ((Cin = (long)extOpen(Cin_name,1005L)) == 0L) {
  2438.                   ierror (NULL, 504);
  2439.                   err = 1;
  2440.                   Cin_name = '\0';
  2441.                } else {
  2442.                   Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin;
  2443.                   ci = (struct FileHandle *)(((long)Cin)<<2);
  2444.                   Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC);
  2445.                   oldbuf = ci->fh_Buf;
  2446.                   if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
  2447.                      ci->fh_Buf = (long)Cin_buf>>2;
  2448.                }
  2449.             }
  2450.             if (Cout_name) {
  2451.                if (Cout_append && (Cout =(long)extOpen(Cout_name, 1005L)) ) {
  2452.                      Seek(Cout, 0L, 1L);
  2453.                } else {
  2454.                   Cout = (long)extOpen(Cout_name,1006L);
  2455.                }
  2456.                if (Cout == NULL) {
  2457.                   err = 1;
  2458.                   ierror (NULL, 504);
  2459.                   Cout_name = '\0';
  2460.                   Cout_append = 0;
  2461.                } else {
  2462.                   Myprocess->pr_COS = _devtab[stdout->_unit].fd = Cout;
  2463.                }
  2464.             }
  2465.          }
  2466.          if (ac < Command[ccno].minargs + 1) {
  2467.             ierror (NULL, 500);
  2468.             err = -1;
  2469.          } else if (!err) {
  2470.             i = (*Command[ccno].func)(avline, Command[ccno].val);
  2471.             if (i < 0)
  2472.                i = 20;
  2473.             err = i;
  2474.          }
  2475.          free (avline);
  2476.          if (E_stack == 0 && Lastresult != err) {
  2477.             Lastresult = err;
  2478.             seterr();
  2479.          }
  2480.          if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
  2481.             if (Cin_name) {
  2482.                fflush(stdin);
  2483.                clearerr(stdin);
  2484.                ci->fh_Buf = oldbuf;
  2485.                extClose(Cin);
  2486.                FreeMem(Cin_buf, 202L);
  2487.             }
  2488.             if (Cout_name) {
  2489.                fflush(stdout);
  2490.                clearerr(stdout);
  2491.                stdout->_flags &= ~_DIRTY;    /* because of nil: device */
  2492.                extClose(Cout);
  2493.                Cout_append = 0;
  2494.             }
  2495.          }
  2496.          Myprocess->pr_CIS =  _devtab[stdin->_unit].fd  = oldcin;
  2497.          Myprocess->pr_COS =  _devtab[stdout->_unit].fd = oldcout;
  2498.       }
  2499.  
  2500.       if (Cin_ispipe && Cin_name)
  2501.          DeleteFile(Cin_name);
  2502.       if (Cout_ispipe) {
  2503.          Cin_name = Cout_name;         /* ok to assign.. static name */
  2504.          Cin_ispipe = 1;
  2505.       } else {
  2506.          Cin_name = '\0';
  2507.       }
  2508.       Cout_name = '\0';
  2509.       Cout_ispipe = 0;
  2510.       elast = save_elast;
  2511.    }
  2512.    mpop_tobase();                      /* free arguments   */
  2513.    mpush_base();                       /* push dummy base  */
  2514.  
  2515. done0:
  2516.    {
  2517.       char *str;
  2518.       if (err && E_stack == 0) {
  2519.          str = get_var(LEVEL_SET, v_except);
  2520.          if (err >= ((str)?atoi(str):1)) {
  2521.             if (str) {
  2522.                ++H_stack;
  2523.                ++E_stack;
  2524.                exec_command(str);
  2525.                --E_stack;
  2526.                --H_stack;
  2527.             } else {
  2528.                Exec_abortline = 1;
  2529.             }
  2530.          }
  2531.       }
  2532.       if (elast != 0 && Exec_abortline == 0)
  2533.          err = fcomm(nextstr, 0);
  2534.       Exec_abortline = 0;
  2535.       if (Cin_name)
  2536.          DeleteFile(Cin_name);
  2537.       Cin_name = NULL;
  2538.       Cin_ispipe = 0;
  2539.    }
  2540. done1:
  2541.    mpop_tobase();
  2542.    if (freeok)
  2543.       free(str);
  2544.    --alias_count;
  2545.    return ((int)err);                  /* TRUE = error occured    */
  2546. }
  2547.  
  2548.  
  2549. char *
  2550. exarg(ptr)
  2551. unsigned char **ptr;
  2552. {
  2553.    register unsigned char *end;
  2554.    register unsigned char *start;
  2555.  
  2556.    start = end = *ptr;
  2557.    while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
  2558.       ++end;
  2559.    elast = *end;
  2560.    *end = '\0';
  2561.    *ptr = end + 1;
  2562.    return ((char *)start);
  2563. }
  2564.  
  2565. static char **Mlist;
  2566.  
  2567. mpush_base()
  2568. {
  2569.    char *str;
  2570.  
  2571.    str = malloc(5);
  2572.    *(char ***)str = Mlist;
  2573.    str[4] = 0;
  2574.    Mlist = (char **)str;
  2575. }
  2576.  
  2577. char *
  2578. mpush(bytes)
  2579. {
  2580.    char *str;
  2581.  
  2582.    str = malloc(6 + bytes + 2);   /* may need extra 2 bytes in do_run() */
  2583.    *(char ***)str = Mlist;
  2584.    str[4] = 1;
  2585.    Mlist = (char **)str;
  2586.    return (str + 5);
  2587. }
  2588.  
  2589. mpop_tobase()
  2590. {
  2591.    register char *next;
  2592.    while (Mlist) {
  2593.       next = *Mlist;
  2594.       if (((char *)Mlist)[4] == 0) {
  2595.          free (Mlist);
  2596.          Mlist = (char **)next;
  2597.          break;
  2598.       }
  2599.       free (Mlist);
  2600.       Mlist = (char **)next;
  2601.    }
  2602. }
  2603.  
  2604.  
  2605. /*
  2606.  * Insert 'from' string in front of 'str' while deleting the
  2607.  * first entry in 'str'.  if freeok is set, then 'str' will be
  2608.  * free'd
  2609.  */
  2610.  
  2611.  
  2612.  
  2613. char *
  2614. format_insert_string(str, from, freeok)
  2615. char *str;
  2616. char *from;
  2617. int *freeok;
  2618. {
  2619.    register char *new1, *new2;
  2620.    register unsigned char *strskip;
  2621.    int len;
  2622.  
  2623.    for (strskip = (unsigned char *)str;
  2624.                    *strskip && *strskip != ' ' 
  2625.                    && *strskip != ';' && *strskip != '|'
  2626.                    && *strskip != 0x80; ++strskip);
  2627.    len = strlen(from);
  2628.    new1 = malloc((len << 2) + 2);
  2629.    preformat(from, new1);
  2630.    len = strlen(new1) + strlen(strskip);
  2631.    new2 = malloc(len+2);
  2632.    strcpy(new2, new1);
  2633.    strcat(new2, strskip);
  2634.    new2[len+1] = 0;
  2635.    free (new1);
  2636.    if (*freeok)
  2637.       free (str);
  2638.    *freeok = 1;
  2639.    return (new2);
  2640. }
  2641.  
  2642. cmd_stat(str)
  2643. char *str;
  2644. {
  2645.    return(Command[find_command(str)].stat);
  2646. }
  2647.  
  2648. find_command(str)
  2649. char *str;
  2650. {
  2651.    register unsigned int i;
  2652.    int len = strlen(str);
  2653.  
  2654.    if (*str >= '0'  &&  *str <= '9')
  2655.       return (1);
  2656.    for (i = 0; Command[i].func; ++i) {
  2657.       if (strncmp (str, Command[i].name, len) == 0)
  2658.          return (i);
  2659.    }
  2660.    return (0);
  2661. }
  2662.  
  2663. do_help()
  2664. {
  2665.    register struct COMMAND *com;
  2666.    int i= 0;
  2667.  
  2668.  
  2669.    for (com = &Command[2]; com->func; ++com) {
  2670.       printf ("%-12s", com->name);
  2671.       if (++i  % 6 == 0) printf("\n");
  2672.    }
  2673.    printf("\n");
  2674.    return(0);
  2675. }
  2676.  
  2677. char *push_cpy(s)
  2678. char *s;
  2679. {
  2680. return strcpy(mpush(strlen(s)), s);
  2681. }
  2682. SHAR_EOF
  2683. #    End of shell archive
  2684. exit 0
  2685. -- 
  2686. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2687. Have five nice days.
  2688.